{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit modMd5;

interface

uses Classes, DCPcrypt2, DCPmd5, SysUtils;


type
    // 16 octets = 4*4 octets = 4 integer
    TMd5HashInfo = array[0..15] of byte;


   procedure md5Free;
   function md5Create: TDCP_md5;

   function md5Stream(fStream: TStream; Size: Int64): TMd5HashInfo;
   function md5String(str: String): TMd5HashInfo;


   function md5StringX(str: String): string;

   function md5ArrayToStr(a: TMd5HashInfo): string;

   function md5IsEgal(h1, h2: TMd5HashInfo): boolean;
   function md5Somme(h1: TMd5HashInfo): integer;

   function md5StrToArray(str: string): TMd5HashInfo;


var
   MemMd5: TDCP_md5;


implementation

function md5Somme(h1: TMd5HashInfo): integer;
var i: integer;
begin

    Result := 0;
    for i := 0 to 15 do begin
       Result := Result + h1[i];
    end;

end;

function md5IsEgal(h1, h2: TMd5HashInfo): boolean;
var h1x: array[0..3] of integer absolute h1;
    h2x: array[0..3] of integer absolute h2;
    i :integer;
begin

   Result := false;
   
   for i := 0 to 3 do begin

      if h1x[i] <> h2x[i] then begin
         exit;
      end;
   end;

   Result := true;

end;


function md5ArrayToStr(a: TMd5HashInfo): string;
var i: integer;
begin
    Result := '';
    for i := 0 to 15 do
        Result := Result + IntToHex(a[i],2);

    Result := lowercase(Result);
end;

function md5StrToArray(str: string): TMd5HashInfo;
var
    currByte: integer;
    indice: integer;
begin

    indice := 0;

    if length(str) <> (SizeOf(Result) * 2) then begin
       FillChar(Result, SizeOf(Result), 0);
       exit;
    end;

    while (indice < (SizeOf(Result))) do begin
       currByte := StrToInt('0x' + copy(str, (indice shl 1) + 1, 2));

       Result[indice] := currByte;
       Inc(indice);
    end;

end;

// fait le md5 d'un string et renvoi le md5 en string
function md5StringX(str: String): string;
begin
   Result := md5ArrayToStr(md5String(str));
end;

function md5String(str: String): TMd5HashInfo;
begin
    md5Create;

    try
       MemMd5.Init;
       MemMd5.UpdateStr(Str);
       MemMd5.Final(Result);
    except
       FillChar(Result, SizeOf(Result), 0);
    end;

end;


function md5Stream(fStream: TStream; Size: Int64): TMd5HashInfo;
begin
    md5Create;

    try
       MemMd5.Init;
       MemMd5.UpdateStream(fStream, Size);
       MemMd5.Final(Result);
    except
       FillChar(Result, SizeOf(Result), 0);
    end;

end;

function md5Create: TDCP_md5;
begin
    if MemMd5 = nil then begin
       MemMd5 := TDCP_md5.Create(nil);
    end;

    Result := MemMd5;
end;

procedure md5Free;
begin
    if MemMd5 <> nil then begin
       MemMd5.Free;
       MemMd5 := nil;
    end;

end;


initialization
    MemMd5 := nil;

finalization
    md5Free;

end.
